package com.defangit.production.orm;

import com.defangit.production.bll.MaterialBillBll;
import com.defangit.production.domain.*;
import laogen.hibernate.CommonFinder;
import laogen.hibernate.CommonService;
import laogen.lang.exception.ParameterNotValidException;
import laogen.util.UniqueNoBuilder;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import java.time.LocalDateTime;
import java.util.List;

/**
 * Created by zhangfagen on 2018/6/12.
 */
public class MaterialBillService extends CommonService<MaterialBill> implements MaterialBillBll {
    private static UniqueNoBuilder noBuilder = UniqueNoBuilder.getInstance("material.bill", (nos) -> {
        List<String> exists = HibernateUtil
                .INSTANCE
                .getSessionFactory()
                .getCurrentSession()
                .createCriteria(MaterialBill.class)
                .add(Restrictions.in("no", nos))
                .setProjection(Projections.property("no"))
                .list();
        nos.removeAll(exists);
    });
    /**
     * 添加材料申领单
     *
     * @param processId 材料申领单所属的工序派工单
     * @param bill      要添加的材料申领单
     * @param authorId    申请人
     * @return 添加后的材料申领单
     */
    @Override
    public MaterialBill addMaterialBill(int processId, MaterialBill bill,Integer authorId) {
        if(bill==null) throw ParameterNotValidException.nullParameter("材料申领单");
        ProductionProcess productionProcess  = new ProductionProcessService().get(processId).orElseThrow(()->ParameterNotValidException.zeroIdOrEntityNonExist("工序订单"));
        Operator author = new OperatorService().get(authorId).orElseThrow(()->ParameterNotValidException.zeroIdOrEntityNonExist("负责人信息异常"));
        bill.setProcess(productionProcess);
        bill.setFounder(author);
        bill.setNo(noBuilder.next());
        add(bill);
        commitSession();
        return get(bill.getId()).orElseThrow(()->ParameterNotValidException.zeroIdOrEntityNonExist("材料申领单"));
    }

    /**
     * @param billId,领料单
     * @param liableId 审核人
     **/
    public MaterialBill addMaterialLiable(Integer billId,Integer liableId) {
        MaterialBill materialBill = get(billId).orElseThrow(()->ParameterNotValidException.zeroIdOrEntityNonExist("领料单信息异常"));
        Operator operator = new OperatorService().get(liableId).orElseThrow(()->ParameterNotValidException.zeroIdOrEntityNonExist("用户信息异常"));
        if (materialBill.getLiables().parallelStream().anyMatch(liable->liable.getId()==liableId)) {
            throw ParameterNotValidException.constraintNotSatisfy("已审核","不要重复审核");
        }
        materialBill.getLiables().add(operator);
        update(materialBill);
        commitSession();
        return materialBill;
    }

    @Override
    public MaterialBill updateMaterialBill(MaterialBill bill) {
        return null;
    }

    @Override
    public boolean deleteMaterialBill(int billId) {
        return false;
    }

    @Override
    public MaterialBillFinder findAll() {
        return new MaterialBillFinderImp();
    }

    public class MaterialBillFinderImp extends CommonFinder<MaterialBill> implements MaterialBillFinder{
        private DetachedCriteria materialsBillCriteria;
        private MaterialBillFinderImp(){
            this.materialsBillCriteria = detachedAll();
        }


        @Override
        public Criteria getCriteria() {
            this.materialsBillCriteria = this.materialsBillCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            return this.materialsBillCriteria.getExecutableCriteria(getSession());
        }

        @Override
        public DetachedCriteria getDetachedCriteria() {
            return materialsBillCriteria;
        }

        @Override
        public MaterialBillFinder materialId(Integer id) {
            return null;
        }

        @Override
        public MaterialBillFinder materialNo(String no) {
            return null;
        }

        @Override
        public MaterialBillFinder operatorId(Integer operatorId) {
            return null;
        }

        @Override
        public MaterialBillFinder materialTime(LocalDateTime min, LocalDateTime max) {
            return null;
        }
    }
}
